package org.ee.system.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.ee.core.api.Result;
import org.ee.core.constant.ResultCode;
import org.ee.core.util.GuavaUtil;
import org.ee.system.domain.UserInfo;
import org.ee.system.service.JwtProvider;
import org.ee.system.service.UserService;
import org.ee.system.service.bo.UserDetailBo;
import org.ee.system.vo.LoginVo;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

/**
 * 授权认证接口
 * @Author jokr
 * @Date 2025/8/20 下午3:00
 */
@RestController
@RequestMapping("/auth")
@Tag(name = "授权认证管理",description = "授权认证管理模块，包含登录，注册和RefreshToken")
public class AuthController {

    private final AuthenticationManager authenticationManager;
    private final JwtProvider jwtProvider;
    private final UserService userService;

    public AuthController(AuthenticationManager authenticationManager, JwtProvider jwtProvider, UserService userService) {
        this.authenticationManager = authenticationManager;
        this.jwtProvider = jwtProvider;
        this.userService = userService;
    }

    /**
     * 登录，获取token
     * @param username 用户名
     * @param password 密码
     * @return token
     */
    @Operation(summary = "登录", description = "返回登录Token")
    @PostMapping("/login")
    public Result<LoginVo> login(@RequestParam(value = "username") String username,
                        @RequestParam(value = "password") String password) {
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(username, password);
        Authentication authentication;
        try {
            authentication = authenticationManager.authenticate(authenticationToken);
        }catch(BadCredentialsException e){
            return Result.success("用户名或者密码错误",null);
        }
        UserDetailBo bo= (UserDetailBo) authentication.getPrincipal();
        Map<String, Object> extraClaims= GuavaUtil.newHashMap("username",bo.getUsername());
        String token = jwtProvider.generateToken(bo.getUserId().toString(), extraClaims);
        String refreshToken = jwtProvider.refreshToken(bo.getUserId().toString());
        LoginVo vo=new LoginVo(token,refreshToken);
        return Result.success(vo);
    }

    /**
     * 刷新token
     * 请求拦截器：所有请求自动带上 Authorization: Bearer token。
     * 响应拦截器：
     * 如果接口返回 401 Unauthorized → 用 refreshToken 去 /auth/refresh 换新 token。
     * 换到新 token 后，更新本地存储，并 重试原请求。
     * 如果 refreshToken 也过期 → 直接跳转登录页。
     *
     * @param body
     * @return
     */
    @Operation(summary = "刷新Token",description = "返回新的Token")
    @RequestMapping("/refresh")
    public Result refreshToken(@RequestBody Map<String,Object> body) {
        String refreshToken=body.get("refreshToken").toString();
        if(!jwtProvider.validToken(refreshToken)){
            return Result.failure(ResultCode.UNAUTHORIZED.getCode(),"refreshToken已失效，请重新登录");
        }
        String userId= jwtProvider.getUsername(refreshToken);
        UserInfo model= userService.getSysUserById(Long.valueOf(userId));
        if(model==null){
            return Result.failure("用户不存在");
        }
        String newToken=jwtProvider.generateToken(userId,null);
        // 注意：refreshToken 通常也会设置较长的过期时间
        // 如果你希望刷新时也更新 refreshToken，可以在这里一并生成，看情况
        String newRefreshToken=jwtProvider.refreshToken(userId);
//        LoginVo vo = new LoginVo();
//        vo.setToken(newToken);
//        vo.setToken(refreshToken);
        LoginVo vo=new LoginVo(newToken,newRefreshToken);
        return Result.success(vo);
    }

    /**
     * 注册
     *
     * @param username 用户名
     * @param password 密码
     * @return result json对象
     */
    @Operation(summary = "注册",description = "返回是否注册成功")
    @PostMapping("/register")
    public Result<String> register(@RequestParam(value = "username") String username,
                           @RequestParam(value = "password") String password) {
        UserInfo sysUser = new UserInfo();
        sysUser.setUserName(username);
        sysUser.setUserPwd(password);

        try {
            userService.register(sysUser);
            return Result.success("注册成功");
        } catch (RuntimeException e) {
            return Result.failure(e.getMessage());
        }
    }

}
